package soul.utils;

import java.math.BigDecimal;

/**
 * Created by yfxiaodou on 2016/5/17.
 * 高斯分布算法，用于生产正态分布的数据
 * 红包生成
 */
public class HongBaoAlgorithm {
    /**
     * 金额的精度：保留两位小数
     */
    private static int scale = 2;

    /**
     * 普通玩法
     * <p>
     * 输入金额、人数，随机输出金额列表，例如：<br>
     * 输入：1.0 3<br>
     * 输出：0.11 0.37 0.52
     * </p>
     * @return
     */
    public static BigDecimal[] generalPlay(final BigDecimal money,
                                           int numberOfPeople) {
        // 检验参数的合法性
        checkGeneralPlayValidParam(money, numberOfPeople);
        // 将金额转化为分，就能转化为整数
        BigDecimal divisor = new BigDecimal(100);
        int n = money.multiply(divisor).intValue();
        BigDecimal[] result = new BigDecimal[numberOfPeople];
        int m = numberOfPeople;
        if (m == 1) {
            result[0] =money;
        } else {
            int index = 0;
            for (int i = 0; i < n; i++) {
                long bigrand = bigRand();
                if (bigrand % (n - i) < m) {
                    result[index++] = new BigDecimal(i + 1).divide(divisor, scale,
                            BigDecimal.ROUND_HALF_UP);
                    m--;
                }
            }
            // 分区间处理
            for (int i = numberOfPeople - 1; i > 0; i--) {
                if (i == (numberOfPeople - 1)) {
                    // 最后一个就取剩余的
                    result[i] = money.subtract(result[i - 1]);
                } else {
                    result[i] = result[i].subtract(result[i - 1]);
                }
            }
        }
        return result;
    }

    /**
     * 产生一个很大的随机整数
     * @return long
     */
    private static long bigRand() {
        return (long) (Math.random() * Integer.MAX_VALUE) + Integer.MAX_VALUE;
    }

    /**
     * 检查方法{@link #generalPlay(BigDecimal, int)}参数的有效性
     */
    private static void checkGeneralPlayValidParam(final BigDecimal money,
                                                   int numberOfPeople) {
        // 确保人数大于等于1
        if (numberOfPeople < 1) {
            throw new RuntimeException("人数 " + numberOfPeople + " 应该大于0！");
        }
        // 确保每个人至少能分到0.01元
        if (money.compareTo(new BigDecimal("0.01").multiply(new BigDecimal(
                numberOfPeople))) < 0) {
            throw new RuntimeException("人数太多，钱不够分！");
        }
        // 确保money只有两位小数
        if (money.scale() > scale) {
            throw new RuntimeException("金额数据不对，最多保留两位小数！");
        }
    }
}